Skip to content

fix(docs): make the docs site readable to agents that fetch it - #34

Merged
lukaisailovic merged 1 commit into
mainfrom
fix/docs-md-cross-links
Jun 25, 2026
Merged

fix(docs): make the docs site readable to agents that fetch it#34
lukaisailovic merged 1 commit into
mainfrom
fix/docs-md-cross-links

Conversation

@lukaisailovic

Copy link
Copy Markdown
Owner

Problem

When an agent is pointed at OpenIslands and reaches for the docs, it hits a client-rendered SPA:

  • The docs live at root paths (/introduction, /mcp, …), so a guessed URL like /docs matches no prerendered page. The assets-only Cloudflare deploy answers any unmatched path with a 200 OK SPA shell whose only rendered text is "OpenIslands" — no content, no 404, no signpost.
  • The agent-readable resources already existed (/llms.txt, /llms-full.txt, per-page /<page>.md, /start.md) but nothing advertised them.
  • Once on a .md page, its internal links pointed back at the JS-rendered HTML routes, bouncing the agent out of markdown.

Changes

  • __root.tsx — signpost the plain-text docs from the root, so a JS-less fetch of any path (including the SPA fallback shell) finds them: a rel="alternate" text/markdown link in <head> plus a <noscript> listing /llms-full.txt, /llms.txt, the append-.md trick, and /start.md.
  • source.tslinkToMarkdownSiblings() rewrites internal absolute doc links to their .md sibling (skips the site root, asset files, and external links).
  • {$}.md route — rewrite cross-links to .md and append a footer pointing at /llms-full.txt and /llms.txt.
  • llms.txt route — rewrite the index links to .md and prepend a note telling the agent the .md suffix works for any page it builds itself (per the llms.txt convention of highlighting markdown versions).

Verified against the built output

  • introduction.md / getting-started.md: internal links → .md; external (http://…) and .txt resources untouched; footer present.
  • llms.txt: note prepended, index links rewritten to .md.
  • _shell.html (the fallback for any wrong URL): carries the rel="alternate" link + <noscript> pointer.

Deliberately skipped

Content negotiation (Accept: text/markdown on the same URL — what Mintlify does) needs a request-time server; the docs deploy is assets-only static, so there's no server to read the header. The .md suffix is the static-hosting-compatible equivalent and is already in place.

pnpm build + pnpm typecheck clean; lint shows only pre-existing _splat warnings.

Agents pointed at the docs hit a client-rendered SPA: a wrong URL guess
(e.g. /docs) returns a 200 shell whose only text is "OpenIslands", with no
pointer to the plain-text docs that already exist (/llms.txt, /llms-full.txt,
per-page .md). And once on a .md page, its internal links pointed back at the
JS-rendered HTML routes, bouncing the agent out of markdown.

- __root.tsx: signpost the plain-text docs from the root (so a JS-less fetch
  of any path, incl. the SPA fallback shell, finds them): a
  rel="alternate" text/markdown link plus a <noscript> listing
  /llms-full.txt, /llms.txt, the append-.md trick, and /start.md.
- source.ts: linkToMarkdownSiblings() rewrites internal absolute doc links to
  their .md sibling (skips the root, asset files, and external links).
- {$}.md route: rewrite cross-links to .md and append a footer pointing at
  /llms-full.txt and /llms.txt.
- llms.txt route: rewrite the index links to .md and prepend a note telling
  the agent the .md suffix works for any page (per the llms.txt convention of
  highlighting markdown versions).

Content negotiation (Accept: text/markdown on the same URL) is intentionally
not done — it needs a request-time server, and the docs deploy is assets-only
static. The .md suffix is the static-compatible equivalent.
@lukaisailovic
lukaisailovic merged commit 92521ee into main Jun 25, 2026
2 checks passed
@lukaisailovic
lukaisailovic deleted the fix/docs-md-cross-links branch June 25, 2026 17:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant